package golf

import	(
	"os"
	"scanner"
	"fmt"
	//"bytes"
	"container/list"
)

type Golf struct {
	filename string
	fh *os.File
	scanner *scanner.Scanner
	lines *list.List
	Cur_pos scanner.Position
}

func dumpPos( pos scanner.Position ) string  {
 //Filename string // filename, if any
 //Offset   int    // byte offset, starting at 0
 //Line     int    // line number, starting at 1
 //Column   int    // column number, starting at 0 (character count per line)
 return fmt.Sprintf("Line:%v, Col;%v", pos.Line, pos.Column)
}//dumpPos()



func NewGolf(filename string) *Golf {

	fh, err := os.Open( filename, os.O_RDONLY, 0)
	if err != nil {
		panic( err.String() )
	}

	var s scanner.Scanner
	s.Init(fh)
	//s.Whitespace = 0
	s.Mode = scanner.ScanIdents | scanner.ScanInts |
			scanner.ScanFloats | scanner.ScanChars |
			scanner.ScanStrings | scanner.ScanRawStrings |
			scanner.ScanComments | scanner.SkipComments

	l := list.New()

	return &Golf{filename:filename,fh:fh, scanner:&s, lines:l}
}//NewGolf()

func (gc *Golf) NextToken() *golfToken {

	b_pos := gc.scanner.Pos()
	//fmt.Printf("Pos Before Scan:%v\n", dumpPos(b_pos))

	tok := gc.scanner.Scan()
	if scanner.EOF == tok {
		return nil
	}

	a_pos := gc.scanner.Pos()

	pos := a_pos
	//fmt.Printf("Pos After Scan:%v\n", dumpPos(a_pos))
	//pos := gc.scanner.Pos()

	//if tok == scanner.Comment || gc.scanner.Peek() == '\n' {
	if gc.scanner.Peek() == '\n' && (b_pos.Line != a_pos.Line) {
		pos.Line = b_pos.Line
	}

	return newGolfToken(tok, gc.scanner.TokenText(), pos)
}//NextToken()

func (gc *Golf) Parse() os.Error {

	gtok := gc.NextToken()
	c_line := gtok.Pos.Line
	c_list := list.New();

	for ; gtok != nil; gtok = gc.NextToken() {

		//if gc.scanner.Whitespace & (1<<uint(gtok.Tok)) != 0  {
			//continue
		//}

		if c_line != gtok.Pos.Line {
			//fmt.Printf("moved to line:%v\n", gtok.Pos.Line)
			ngl := newGolfLine(c_list, c_line)
			gc.lines.PushBack( ngl )
			c_line = gtok.Pos.Line
			c_list = list.New();
			fmt.Printf("%v\n", ngl)
		}

		c_list.PushBack(gtok)
		//fmt.Printf("%v:%v:%v\n",c_line, gtok.Pos.Line, gtok )
	}

	// Get that last line
	ngl := newGolfLine(c_list, c_line)
	gc.lines.PushBack( ngl )
	fmt.Printf("%v\n", ngl)

	return nil
}//Parse()

func (ngc *Golf) Close() {
	ngc.fh.Close()

	ngc.filename = ""
	ngc.scanner = nil
}//Close()
